#include <sum_btimer.h>
#include <sum_csr.h>
#include <sum_eclic.h>
#include <sum_gpio.h>
#include <sum_rcu.h>
#include <sum_timer.h>
#include <sum_usart.h>
#include <sum_wfi.h>
#include <sys_mem.h>
#include <util_fifo.h>
#include <util_trans.h>

#define APB2_FREQ_DEFAULT 8000000
#define TIMER1_FREQ_DEFAULT 8000000
#define TIMER1_CLOCK_PSC 40000

#define TIMER2_FREQ_DEFAULT 8000000
#define TIMER2_CLOCK_PSC 400
#define TIMER2_TIMES_MAXN 20000
#define BUFFER_SIZE_2_POWER 8

#define TIMER1_TIMES_MAXN 100
#define TIMER1_HIGH_TIMES_MAXN 70

// RCU中将GPIOA、USART0、TIMER1、TIMER2上电
static void _enable_gpioa_usart0_timer2_timer4(void) {
	rcu_apb1_0_7_s apb1_0_7 = {
		.TIMER1 = 1,
		.TIMER2 = 1,
	};
	rcu_apb1_0_7_en_di(apb1_0_7);

	rcu_apb2_s apb2 = {
		.apb2_0_7.GPIOA = 1,
		.apb2_8_15.USART0 = 1,
	};
	rcu_apb2_en_di(apb2);
}

// 配置GPIO引脚功能
static void _setup_gpio(void) {
	gpio_ctl_0_7_s gpioa_ctl_0_7 = {
		// A1的配置：低速输出、AF、推挽
		.pin1_ctl = GPIO_OUT_AF_PP_2MHZ,

		// A7的配置：输入、浮空
		.pin7_ctl = GPIO_IN_FLOAT,
	};
	gpio_setup_pin_0_7(GPIOA_Q, gpioa_ctl_0_7);

	gpio_ctl_8_15_s gpioa_ctl_8_15 = {
		// A9的配置：低速输出、AF、推挽
		.pin9_ctl = GPIO_OUT_AF_PP_2MHZ,

		// A10的配置：输入、浮空
		.pin10_ctl = GPIO_IN_FLOAT,
	};
	gpio_setup_pin_8_15(GPIOA_Q, gpioa_ctl_8_15);
}

// 使能USART0发送功能，关闭其它。
static void _enable_send_only(void) {
	usart_ctl0_expl_s ctl0 = {
		.usart_en = 1,
		.trans_en = 1,
	};
	usart_setup_0(USART0_Q, ctl0);
}

// 使能USART0发送功能、可发送中断，关闭其它。
static void _enable_send_tbe(void) {
	usart_ctl0_expl_s ctl0 = {
		.usart_en = 1,
		.trans_en = 1,
		.trans_avl_inter_en = 1,
	};
	usart_setup_0(USART0_Q, ctl0);
}

// 串口输出缓冲区
static struct {
	fifo8_v fifo8;
	u8_s buffer_a[1 << BUFFER_SIZE_2_POWER];
} g_fifo8_buffer;

static void _init_fifo() {
	fifo8_init(&(g_fifo8_buffer.fifo8), BUFFER_SIZE_2_POWER);
}

static void _put_char_to_buf(u32_s byte) {
	fifo8_in_byte(&(g_fifo8_buffer.fifo8), byte);
	_enable_send_tbe();
}

// 串口中断
static void _usart0_irq(void) {
	usart_stat_expl_s stat = usart_get_stat(USART0_Q);
	fifo8_v* fifo8_p = &(g_fifo8_buffer.fifo8);
	if (stat.trans_avl) {
		if (fifo8_has_data(fifo8_p)) {
			u32_s byte = fifo8_out_byte(fifo8_p);
			usart_wn_byte(USART0_Q, byte);
		} else {
			_enable_send_only();
		}
	}
}

// 定时器2中断
static void _timer2_irq(void) {
	// _put_char_to_buf('0');
	timer_intf_expl_s cur_int_flag = timer_get_int_flag(TIMER2_Q);
	timer_intf_expl_s int_flag_clear = {0};
	timer_set_int_flag(TIMER2_Q, int_flag_clear);
	// 读时间寄存器，获得上升沿的时间。
	if (cur_int_flag.interrupt.channel_0) {
		trans_write_str("Up stick: ", _put_char_to_buf);
		u32_s stick =
			timer_get_channel_cmp_value(TIMER2_Q, TIMER_CHCV_0_R);
		trans_write_udec(stick, _put_char_to_buf);
		trans_write_str(". ", _put_char_to_buf);
	}
	// 读时间寄存器，获得下降沿的时间。
	if (cur_int_flag.interrupt.channel_1) {
		trans_write_str("Down stick: ", _put_char_to_buf);
		u32_s stick =
			timer_get_channel_cmp_value(TIMER2_Q, TIMER_CHCV_1_R);
		trans_write_udec(stick, _put_char_to_buf);
		trans_write_str(".\n", _put_char_to_buf);
	}
}

// 初始化TIMER1，用于输出PWM。
static void _init_timer1(void) {
	timer_set_clock_amount_per_count(TIMER1_Q, TIMER1_CLOCK_PSC);
	timer_set_times_per_cycle(TIMER1_Q, TIMER1_TIMES_MAXN);
	timer_chctl_expl_s chctl0 = {
		.channel_13.chctl_out.mode = TIMER_CHCTL_OUT,
		.channel_13.chctl_out.fast_en = 1,
		.channel_13.chctl_out.ctl = TIMER_CHCTL_OUT_LOWER_VALID,
		.channel_13.chctl_out.clear_en = 0,
	};
	timer_channel_setup(TIMER1_Q, TIMER_CHCTL_0_R, chctl0);
	timer_wreg_chcv(TIMER1_Q, TIMER_CHCV_1_R, TIMER1_HIGH_TIMES_MAXN);
	timer_chctl2_expl_s chctl2 = {
		.channel_1_en = 1,
		.channel_1_polarity_neg = 1,
	};
	timer_channel_setup_2(TIMER1_Q, chctl2);
	// 部分配置+开始
	timer_ctl0_expl_s ctl0 = {
		.counter_en = 1,
		.single_pulse_mode = 0,
		.direction = TIMER_CTL0_DIRECTION_UP,
		.counter_align = TIMER_CTL0_COUNTER_ALIGN_EDGE,
		.clock_prescale = TIMER_CTL0_CLOCK_NO_DIV,
	};
	timer_setup_0(TIMER1_Q, ctl0);
}

// 初始化TIMER2，用于读PWM。
static void _init_timer2(void) {
	timer_set_clock_amount_per_count(TIMER2_Q, TIMER2_CLOCK_PSC);
	timer_set_times_per_cycle(TIMER2_Q, TIMER2_TIMES_MAXN);
	// 从模式为复位，来源为CI1FE1。
	timer_smcfg_expl_s smcfg = {
		.slave_mode = TIMER_SMC_SLAVE_MODE_RESTART,
		.trigger_sel = TIMER_SMC_TRIGGER_SEL_CI1FE1,
		.master_slave_mode_en = 0,
		.external_trigger_filter =
			TIMER_SMC_EXTERNAL_CLOCK_DIV_1_EVENT_DIV_1,
		.external_trigger_prescale_power_2 = 0,
		.external_clock_mode_1_en = 0,
	};
	timer_setup_slave_mode(TIMER2_Q, smcfg);
	// 通道0、通道1配置
	timer_chctl_expl_s chctl0 = {
		.channel_02.chctl_in.mode = TIMER_CHCTL_IN_IS0_TO_CI1FE0,
		.channel_02.chctl_in.prescale_2_power = 0,
		.channel_02.chctl_in.filter_ctl =
			TIMER_CHCTL_IN_FILTER_F_DTS_N_1,
		.channel_13.chctl_in.mode = TIMER_CHCTL_IN_IS0_TO_CI0FE0,
		.channel_13.chctl_in.prescale_2_power = 0,
		.channel_13.chctl_in.filter_ctl =
			TIMER_CHCTL_IN_FILTER_F_DTS_N_1,
	};
	timer_channel_setup(TIMER2_Q, TIMER_CHCTL_0_R, chctl0);
	// 极性配置
	timer_chctl2_expl_s chctl2 = {
		.channel_0_en = 1,
		.channel_0_polarity_neg = 0,
		.channel_1_en = 1,
		.channel_1_polarity_neg = 1,
	};
	timer_channel_setup_2(TIMER2_Q, chctl2);
	// 中断配置
	timer_dmainten_expl_s dmainten = {
		.int_en.channel_0 = 1,
		.int_en.channel_1 = 1,
	};
	timer_en_di_dma_int(TIMER2_Q, dmainten);
	// 部分配置+定时器使能
	timer_ctl0_expl_s ctl0 = {
		.counter_en = 1,
		.single_pulse_mode = 0,
		.direction = TIMER_CTL0_DIRECTION_UP,
		.counter_align = TIMER_CTL0_COUNTER_ALIGN_EDGE,
		.clock_prescale = TIMER_CTL0_CLOCK_NO_DIV,
	};
	timer_setup_0(TIMER2_Q, ctl0);
}

// 中断配置
static void _setup_interrupt(void) {
	// 中断入口地址设为自带的中断入口
	csr_set_default_exti_entry();
	// 中断向量表
	static const __attribute__((aligned(512))) eclic_irqvec_t ivt = {
		.irq_entry_fa[IRQNO_USART0] = _usart0_irq,
		.irq_entry_fa[IRQNO_TIMER2] = _timer2_irq,
	};
	eclic_set_ivt_base(&ivt);
	// 设置中断level和priority，其中调试串口使用最高优先级、可打断一切。
	eclic_set_level_priority_bit_amount(NLBITS_LEVEL_0_PRIORITY_4);
	eclic_clicint_expl_s usart0_clicint = {
		.inter_en.value = 1,
		.attr.vector_mode = 0,
		.level_priority = eclic_set_level_priority(
			NLBITS_LEVEL_1_PRIORITY_3, 0, 0),
	};
	eclic_setup_inter_expl(IRQNO_USART0, usart0_clicint);
	eclic_clicint_expl_s timer_clicint = {
		.inter_en.value = 1,
		.attr.vector_mode = 0,
		.level_priority = eclic_set_level_priority(
			NLBITS_LEVEL_1_PRIORITY_3, 1, 0),
	};
	eclic_setup_inter_expl(IRQNO_TIMER2, timer_clicint);
	// 打开全局中断
	csr_enable_global_interrupt();
}

__attribute__((noreturn, section(".MAIN"))) void user_main(void) {
	mem_scatter_load();
	// 初始化fifo缓冲区
	_init_fifo();

	_enable_gpioa_usart0_timer2_timer4();
	_setup_gpio();
	// 串口配置
	usart_set_baud_rate(USART0_Q, 115200, APB2_FREQ_DEFAULT);
	_enable_send_only();
	// TIMER1配置，用于输出PWM。
	_init_timer1();
	// TIMER2配置，用于读PWM。
	_init_timer2();
	// 异常入口地址直接设为0（理论上该例程中不可能发生异常）。
	csr_enable_eclic_set_entry(0);
	// 中断配置
	_setup_interrupt();

	while (1) {
		wfi();
	}
}
